<template>
  <div>

    <el-upload
        ref="upload"
        v-model:file-list="fileList"
        :list-type="props.type==='pic'?'picture-card':'text'"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove"
        :on-success="handleSuccess"
        :auto-upload="true"
        :http-request="beforeUpload"
        :on-exceed="handleExceed"
        :accept="accept"
        style="width: 400px;"
        :limit="limit"
        action="/upload"
    >

      <el-icon v-if="props.type==='pic'"><Plus /></el-icon>
      <el-button type="primary" v-else>{{btnText}}</el-button>
      <template #tip   v-if="tip">
        <div class="el-upload__tip">
          {tip}
        </div>
      </template>
    </el-upload>
<!--    <el-progress :percentage="curProgress" v-if="curProgress>0" />-->

    <el-dialog v-model="dialogVisible">
      <img w-full :src="dialogImageUrl" alt="Preview Image" />
    </el-dialog>
  </div>

</template>

<script lang="ts" setup>
import { ref ,defineProps,computed,defineEmits,onMounted,watch,withDefaults} from 'vue'
import { Plus } from '@element-plus/icons-vue'
import axios from 'axios'
import {getUploadFileMD5,getImgUrl} from '@/utils/util'
import { genFileId ,ElNotification,ElLoading} from 'element-plus'
import {get} from '@/utils/request'

import type { UploadProps, UploadUserFile } from 'element-plus'

const  defaultUrl=import.meta.env.VITE_BASE_API+'/pwkIssue/upload'

const upList=ref<string>([])

const props=withDefaults(defineProps<{
  modelValue?:  any,
  type?: string,
  accept?: string,
  limit?: number,
  tip?: string,
  uploadUrl?: string,
  btnText?: string,
  urlKey?: string
}>(),{type:'text',accept: '',limit: 1,tip:'',uploadUrl:'/users/upload',btnText: '上传'});


watch(() => props.modelValue, (newValue, oldValue, onCleanup) => {
     if(typeof props.modelValue==='string'){
       upList.value=[]
       fileList.value=[]
       JSON.parse(newValue).forEach((item) => {
         var url=item
         if(props.urlKey){
           url=item[props.urlKey]
         }
         fileList.value.push({url:url,name:url})
         upList.value.push(url)
       })
       emit('update:modelValue', upList.value)
     }
})

const fileList = ref<UploadUserFile[]>([])

const dialogImageUrl = ref('')
const dialogVisible = ref(false)

const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  upList.value = upList.value.filter((item) => {
    return uploadFile.name!==item
  })
  emit('update:modelValue', upList.value)
}

const handleSuccess: UploadProps['onSuccess'] = (res) => {
  upList.value.push(res)
  emit('update:modelValue', upList.value)
  emit('upSuccess',upList.value)
  // if(finishChunk.value==allChunkCount.value) {
  //   curProgress.value=100;
  //   upList.value.push(res)
  //   fileList.value.push({url:getImgUrl(res),name:res})
  //   setTimeout(function(){
  //     curProgress.value=0;
  //   },200)
  // }
}


// 子组件更改父组件的值
const emit = defineEmits()

const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
  console.log('预览',uploadFile)
  if(uploadFile.url.endsWith('.mp4')||uploadFile.url.endsWith('.MP4')){
     window.open(uploadFile.url)
     //location.href=uploadFile.url
  }else {
    dialogImageUrl.value = uploadFile.url!
    dialogVisible.value = true
  }

}

const chunkSize = 1024 * 1024;

const fileSize=ref<number>(0)


const  curProgress=ref(0)


const  waitList=ref<Object[]>([]);

const  allChunkCount=ref(0)


function beforeUpload(option) {
  const loading = ElLoading.service({
    lock: true,
    text: '解析中',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  var file=option.file
  getUploadFileMD5(file).then(res=>{
    var type=file.name.split('.')[1]
    var filename=res+'.'+type;
    get('/users/checkFile',{name:filename}).then(res=>{
        if(res){
          loading.close()
          option.onSuccess(res)
        }else {
          cancelTokens.value.forEach(item=>{
            item()
          })
          cancelTokens.value = []
          if(file.size>chunkSize){
            fileSize.value=file.size
            progressList.value=[];
            const chunkCount = Math.ceil(file.size / chunkSize);
            allChunkCount.value=chunkCount;
            for (let i = 0; i < chunkCount; i++) {
              const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
              const formData = new FormData();
              formData.append('file', chunk);
              formData.append('index', i+"");
              formData.append('total', chunkCount+"");
              formData.append('name', filename);
              // 发送分片到服务器
              if(i<5){
                uploadChunk(formData, i, chunkCount,option);
              }else {
                let retry=new Promise((resolve, reject) => {
                  waitList.value.push(() => {
                    /*将请求挂起*/
                    resolve(uploadChunk(formData, i, chunkCount,option))
                  });
                })
              }
            }
            loading.close()
          }else {
            loading.close()
            allChunkCount.value=1;
            const formData = new FormData();
            formData.append('file', file);
            formData.append('total', "1");
            uploadChunk(formData, 0, 1,option);
          }
        }
    })
  })
  return false;
}

const CancelToken = axios.CancelToken;

const cancelTokens = ref([]);

const instance = axios.create({
  baseURL: import.meta.env.VITE_BASE_API,
  'Content-Type': 'multipart/form-data'
});

const  progressList=ref<number[]>([])

function  uploadChunk(formData, chunkIndex, totalChunks,option) {
  return new Promise((resolve, reject) => {
    instance.post(props.uploadUrl, formData, {
      onUploadProgress: progressEvent => {
        console.log('上传进度',progressEvent)
        progressList.value[chunkIndex]=progressEvent.progress;
        var nowProgress=0;
        var itemProgress=100/totalChunks;
        progressList.value.forEach((item) => {
           nowProgress+=item*itemProgress;
        })
        if(nowProgress>=99){
          nowProgress=99;
        }
        const  progressEvt={percent:Number(nowProgress.toFixed(2)) }
        option.onProgress(progressEvt)
        //curProgress.value=Number(nowProgress.toFixed(2));
      },
      cancelToken: new CancelToken(c => {
        cancelTokens.value.push(c);
      })
    }).then(res => {
      if(waitList.value.length>0){
        waitList.value[0]()
        waitList.value.splice(0,1)
      }
      if(res.data){
        console.log('上传成功-----------------',res)
        cancelAll();
        const  progressEvt={percent:100 }
        option.onProgress(progressEvt)
        option.onSuccess(res.data)
      }
      resolve(res);
    }).catch(err => {

      if(err.code!=='ERR_CANCELED'){
        cancelAll()
        var  meesage=err.response.data.message
        ElNotification.error({
          title: meesage?meesage:"上传失败"
        })
        option.onError(err)
        reject(err);
      }
    });
   });
  }

  function  cancelAll(){
    cancelTokens.value.forEach(item=>{
      try{
        item()
      }catch (e){
        console.log('取消失败',e)
      }
    })
    waitList.value=[];
    cancelTokens.value = []
    console.log('取消所有')
  }

  const  upload=ref(null)

  function  handleExceed(files){
    if(props.limit==1){
      upload.value.clearFiles();
      const file=files[0]
      file.uid=genFileId()
      upload.value.handleStart(file);
      upload.value.submit();
    }else {
      ElNotification.error({
        title: "最多只能上传"+props.limit+"个文件"
      })
    }

  }
</script>
